#!/usr/bin/env bash

# cup.sh
# c upstairs to compile, build, update c files
# ./cup.sh -ubt

export DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PROJECT_DIR=$DIR/..
export TEST_3RD_INC_DIR=$PROJECT_DIR/third/inc
export TEST_3RD_LIB_DIR=$PROJECT_DIR/third/lib

function create_env() {
    cd $PROJECT_DIR
    [ ! -d "source" ] && echo "no folder source" && mkdir source
    [ ! -d "scripts" ] && echo "no folder scripts" && mkdir scripts
    [ ! -d "test" ] && echo "no folder test" && mkdir test
}

function build() {
    cd $PROJECT_DIR
    [ -d "output" ] && rm -rf output
    [ -d "build" ] && rm -rf build
    mkdir build && cd build
    cmake .. -DENABLE_COVERAGE=1
    make
    if [ $? -ne 0 ]; then
        echo ">>> build failed"
    fi
}

function build_test() {
    cd $PROJECT_DIR/test
    [ -d build ] && echo "clean build folder..." && rm -rf build
    mkdir build && cd build
    cmake ..
    make
    if [ $? -ne 0 ]; then
        echo ">>> build failed"
    fi
}

function copy_inc() {
    cd $PROJECT_DIR
    [ -d "$TEST_3RD_INC_DIR" ] && rm -rf $TEST_3RD_INC_DIR
    mkdir -p $TEST_3RD_INC_DIR
    cp -rf $PROJECT_DIR/deps/googletest/googletest/include/* $TEST_3RD_INC_DIR
    cp -rf $PROJECT_DIR/deps/googletest/googlemock/include/* $TEST_3RD_INC_DIR
    cp -rf $PROJECT_DIR/deps/mockcpp/include/* $TEST_3RD_INC_DIR
    cp -rf $PROJECT_DIR/deps/mockcpp/3rdparty/* $TEST_3RD_INC_DIR
    [ -d "$TEST_3RD_LIB_DIR" ] && rm -rf $TEST_3RD_LIB_DIR
    mkdir -p $TEST_3RD_LIB_DIR
    find $PROJECT_DIR/deps -name "lib*.a" -type f -exec cp {} $TEST_3RD_LIB_DIR \;
}

function update() {
    cd $PROJECT_DIR/deps/googletest
    [ -d build ] && echo "clean build folder..." && rm -rf build
    mkdir build && cd build
    cmake ..
    make
    if [ "$?" -ne 0 ]; then
        echo ">>> build failed"
        exit 1
    fi

    cd $PROJECT_DIR/deps/mockcpp
    [ -d build ] && echo "clean build folder..." && rm -rf build
    mkdir build && cd build
    cmake ..
    make
    if [ "$?" -ne 0 ]; then
        echo ">>> build failed"
    fi

    copy_inc
}

function force_update() {
    echo "force_update"
    cd $PROJECT_DIR
    [ -d deps ] && rm -rf deps
    mkdir deps && cd deps
    [ -d "googletest" ] && rm -rf googletest
    wget https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
    find . -name "*.zip" -type f -maxdepth 1 -exec unzip {} \;
    find . -name "google*" -type d -maxdepth 1 -exec mv {} googletest \;
    find . -name "*.zip" -type f -maxdepth 1 -exec rm {} \;

    [ -d "mockcpp" ] && rm -rf mockcpp
    git clone git@github.com:sinojelly/mockcpp.git

    update
}

function run() {
    cd $PROJECT_DIR/test/build
    for ut in $(find . -name "ut_*" -type f); do
        echo "test ut : [${ut}]"
        $ut
        if [ $? -ne 0 ]; then
            echo "test err retcode: [$?]"
            exit 1
        fi
    done
}
function run_target() {
    cd $PROJECT_DIR/test/build
    for ut in $(find . -name "$1" -type f); do
        echo "test ut : [${ut}]"
        $ut
        if [ $? -ne 0 ]; then
            echo "test err retcode: [$?]"
            exit 1
        fi
    done
}
function list() {
    cd $PROJECT_DIR/test/build
    for ut in $(find . -name "ut_*" -type f); do
        echo "list ut: [${ut}]"
    done
}

function clean() {
    cd $PROJECT_DIR
    [ -d "coverage_rate" ] && rm -rf coverage_rate
    [ -d "build" ] && rm -rf build
    cd test
    [ -d "build" ] && rm -rf build
}
function force_clean() {
    cd $PROJECT_DIR
    [ -d "output" ] && rm -rf output
    [ -d deps ] && rm -rf deps
    clean
}

function help() {
    cat <<EOF
OVERVIEW: cup shell for compile executor project

USAGE: ./cup.sh [options] <inputs>

OPTIONS:
    -h help
    -u update googletest lib
    -U force update googletest lib
    -b build source code to lib
    -t build build test exe
    -r run test exe
    -R run special test exe, need para val
    -l list all test exe
    -g gcov and collect coverage
    -o open_html

COMMOM USAGE:
    -r only run test
    -tr build test | run test
    -btr build source| build test | run test
    -btrg build source | build test | run test | coverage
    -btrgo build source | build test | run test | coverage | html
    -ubt update gtest | build source | build test
    -ubtr update gtest | build source | build test | run test
    -ubtrg update gtest | build source | build test | run test | coverage

EOF
}
function printOpt() {
    echo "use opt: [$1], val: [$2]"
}
function noparaval() {
    echo "opt: [$1] no paraval [$2]"
    echo ""
    help
}

function invalid() {
    echo "无效的选项 - $1"
    echo ""
    help
}

function gcov_collection() {
    result_path=coverage_rate

    cd ${PROJECT_DIR}
    [ -d "${result_path}" ] && rm -rf ${result_path}
    mkdir ${result_path}
    lcov -c -d ${PROJECT_DIR}/build -o ${PROJECT_DIR}/${result_path}/cover.info
    genhtml -o ${PROJECT_DIR}/${result_path}/front_end ${PROJECT_DIR}/${result_path}/cover.info
}

function open_html() {
    cd ${PROJECT_DIR}/coverage_rate/front_end
    open index.html
}

function all() {
    update
    build
    build_test
    run
    gcov_collection
    open_html
}

function main() {
    while getopts ":uUbtrR:glohxacC" opt; do
        # printOpt $opt $OPTARG
        case $opt in
        u) update ;;
        U) force_update ;;
        b) build ;;
        t) build_test ;;
        r) run ;;
        R) run_target $OPTARG ;;
        l) list ;;
        g) gcov_collection ;;
        o) open_html ;;
        x) copy_inc ;;
        a) all ;;
        c) clean ;;
        C) force_clean ;;
        h) help ;;
        :)
            noparaval $opt $OPTARG
            exit 1
            ;;
        ?)
            invalid $OPTARG
            exit 2
            ;;
        esac
    done
}

main "$@"
